#include "raycaster.hpp"

Raycaster::Raycaster(Cena* _cena,Grade* _grade,const Vetor& _posicao,const Vetor& _up,const unsigned short _altura,const unsigned short _largura,const unsigned short _profundidade) : cena(_cena), grade(_grade), posicao(_posicao), up(_up),altura(_altura), largura(_largura), profundidade(_profundidade) 
{}

Raycaster::~Raycaster(void) { 
	delete cena;
	delete grade;
}


Tga* Raycaster::cast(void) const {
//	Framebuffer* fb = new Framebuffer(largura,altura);
	Tga* tga = new Tga(altura,largura);
	Vetor d(0.0f,0.0f,grade->getPosicao().z);
	Raio r(posicao,d);
	Vetor ponto;

	Cor cor;
	/*const double gradeX = grade->getLargura().x;
	const double gradeY = grade->getAltura().y;*/
	double teta1;
	double teta2;
//	double px= -1.0;
	double incx = 2.0/largura;
	double incy = 2.0/altura;
	int x;
	#pragma omp parallel for private(x,r,teta1,teta2,cor,ponto) shared(tga)  num_threads(2) 
	for(x = 0;x < largura;x++) {
		double px = incx*x-1.0;
		teta1 = (M_PI/4.0)*px;
		const double cos_teta1 = cos(teta1);
		double py = -1.0;
		for(int y =0;y < altura;y++) {
			teta2 = (M_PI/4.0)*py;
			const double cos_teta2 = cos(teta2);
			r.setDirecao(Vetor(	cos_teta2*sin(teta1),
						sin(teta2),
						-cos_teta2*cos_teta1
						).normaliza());

			int obj = cena->objetoProximo(ponto,r);
			if (obj != -1) {	 /*Indice -1 indica que não há objeto nessa direcao */
				cor = iluminacao.calculaCorRec(obj,r,ponto,cena,profundidade);
			}
	
//			fb->setPixel( px, py, cor);
			tga->setPixel(x,y,cor);
			cor.set(cena->getFundo());	
			py += incy;
		}
		px += incx;
	}
//	fb->show();

//	delete fb;
	return tga;
}
void Raycaster::setCena(Cena* _cena) { cena = _cena; }

void Raycaster::setGrade(Grade* _grade) { grade = _grade; }

void Raycaster::setPosicao(Vetor _posicao) { posicao = _posicao; }

void Raycaster::setUp(Vetor _up) { up = _up; }

void Raycaster::setAltura(int _altura) { altura = _altura; }

void Raycaster::setLargura(int _largura) { largura = _largura; }

Cena* Raycaster::getCena(void) const { return cena; }

Grade* Raycaster::getGrade(void) const { return grade; }

Vetor Raycaster::getPosicao(void) const { return posicao; }

Vetor Raycaster::getUp(void) const { return up; }

int Raycaster::getAltura(void) const { return altura; }

int Raycaster::getLargura(void) const { return largura; }


